home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / tools / utils / twtcp122 / pktdrv / pktdlink / nicdrv.c < prev    next >
C/C++ Source or Header  |  1995-11-25  |  17KB  |  762 lines

  1. /********************************************************************/
  2. /*                                                                    */
  3. /*    Packet driver for D-LINK DE600 ethernet controller                */
  4. /*                                                                    */
  5. /*    Copyleft by P. Mayer, 1992 fortec - TU-Vienna IAEE                */
  6. /*    All rights reserved                                                */
  7. /*                                                                    */
  8. /*    (Pure-C)                                                        */
  9. /********************************************************************/
  10.  
  11. #define LOCKMEM  0x1
  12. #define LOCKALLO 0x2
  13. #define LOCKFREE 0x4
  14. #define LOCKMAIN 0x8
  15. #define LOCKRES  0x10
  16. #define LOCKREC  0x20
  17. #define LOCKNET  0x40
  18.  
  19. #include <stdio.h>
  20. #include <stddef.h>
  21. #include <string.h>
  22. #include <tos.h>
  23. #include <time.h>
  24. #include "nicmem.h"
  25. #include "nicdrv.h"
  26. #include "pktqueue.h"
  27. #include "pktdrv.h"
  28. #include "cookie.h"
  29. #include "inetcust.h"
  30.  
  31. #define noDEBUG
  32. #define noDEBUGINTR
  33. #define noDEBUGPKT
  34.  
  35. #define Bconws(x) dpy = &x;while(*dpy)(Bconout(2,*dpy++))
  36. char str[80];
  37. char *dpy;
  38.  
  39. PKTBUF PPKT[MAXPKT];
  40.  
  41. PKTPOOL PPOOL;
  42.  
  43. extern char locked200;
  44. int  retval;
  45. int     term = 0;
  46. int good = 0;
  47. et_hdr        header;
  48. int mode;
  49.  
  50. void (interrupt *ihandler)(void) = NULL;
  51. extern void lance_interrupt(void);
  52. extern void lance_200interrupt(void);
  53. extern long *old200;
  54.  
  55. int resetNIC(void);  /* reset lance, init datastructures  */
  56.  
  57. PKTPOOL            *p_free;                  /* queue of free packets */
  58. u_short            freecnt;                  /* number of free packets */
  59.  
  60. procref ext_tab[8] =                    /* subfunction table */
  61. {
  62.   net_reset,
  63.   net_open,
  64.   net_release,
  65.   net_send,
  66.   net_getadr,
  67.   net_info,
  68.   (procref)net_pktalloc,
  69.   net_pktfree
  70. };
  71.  
  72. PROTOCOL protos[MAXPROTOCOLS];  /* protocols to serve */
  73. int protocols = 0;              /* number of active protocols */
  74.  
  75. et_stat stat;                   /* statistics block */
  76.  
  77. /*************************************************************
  78.   test for de600 ethernetadapter interface on cartridge port
  79.  *************************************************************/
  80.  
  81. #define NIC_BASE 0xfa0000L
  82.  
  83. typedef unsigned char byte;
  84.  
  85. byte CurTxPage, Mode_RxPg;
  86. int RxPktLen, RxStartAdd, TxStartAdd, CurRxPage, our_type;
  87. byte our_address[6];
  88. int last, LastTxStartAdd;
  89.  
  90. #define WRITE        (0x00 << 1)
  91. #define READ        (0x01 << 1)
  92. #define STATUS        (0x02 << 1)
  93. #define COMMAND        (0x03 << 1)
  94. #define NUL_CMD     (0x0c << 1)
  95. #define RX_LEN        (0x05 << 1)
  96. #define TX_ADR        (0x06 << 1)
  97. #define RW_ADR        (0x07 << 1)
  98.  
  99. #define WRITE_STROBE    (0x08 << 1)
  100.  
  101. #define RXEN        (0x08)
  102. #define TXEN        (0x04)
  103. #define LOOPBACK    (0x0c)
  104. #define RX_NONE        (0x00)
  105. #define RX_ALL        (0x01)
  106. #define RX_BP        (0x02)
  107. #define RX_MBP        (0x03)
  108.  
  109. #define RESET        (0x80)
  110. #define STOP_RESET    (0x00)
  111.  
  112. #define RXBUSY        0x80
  113. #define GOOD        0x40
  114. #define RESET_FLAG    0x20
  115. #define T16            0x10
  116. #define TXBUSY        0x08
  117.  
  118. #define BFRSIZ        2048
  119. #define RUNT        60
  120. #define EADDR_LEN    6
  121. #define HA13        0x20
  122. #define PAGE_0        0x00
  123. #define PAGE_1        0x08
  124. #define PAGE_2        0x10
  125. #define PAGE_3        0x18
  126.  
  127. #define delay()     /* no delay needed for ST */
  128. #define pause()
  129.  
  130. /* defines for access to DE600 */
  131.  
  132. #define WRITE_SUB_FAST(value, cmd) \
  133.     x = *(int*)(base + (int)(((((int)value) << 5) & 0x1e0) + cmd)); \
  134.     x = *(int*)(base + (int)(last = (((((int)value) << 1) & 0x1e0) + ((cmd) ^ WRITE_STROBE)))); \
  135.  
  136. #define WRITE_SUB(value, cmd) \
  137.     x = *(int*)(base + (int)(((((int)value) << 5) & 0x1e0) + cmd | WRITE_STROBE)); \
  138.     delay(); \
  139.     x = *(int*)(base + (int)(((((int)value) << 5) & 0x1e0) + cmd)); \
  140.     delay(); \
  141.     x = *(int*)(base + (int)(((((int)value) << 1) & 0x1e0) + cmd)); \
  142.     delay(); \
  143.     x = *(int*)(base + (int)(last = ((((int)value) << 1) & 0x1e0) + cmd | WRITE_STROBE)); \
  144.  
  145. #define WRITE_SUPER_FAST(value, cmd) \
  146.     x = *(int*)(base + (int)(((((int)value) << 5)) + cmd)); \
  147.     x = *(int*)(base + (int)((((((int)value) << 1) & 0x1e0) + ((cmd) ^ WRITE_STROBE)))); \
  148.  
  149. #define READ_SUB(cmd) \
  150.     x = *(int*)(base + (int)(cmd | WRITE_STROBE)); \
  151.     delay(); \
  152.     x = *(int*)(base + (int)(cmd)); \
  153.     delay(); \
  154.     y = (*(int*)(base + (int)(cmd)) & 0xf0) ^ 0x80; \
  155.      x = *(int*)(base + (cmd | WRITE_STROBE)); \
  156.     delay(); \
  157.      y = (y >> 4) | ((*(int*)(base + (int)(last = (cmd | WRITE_STROBE))) & 0xf0) ^ 0x80); \
  158.  
  159. #define READ_STAT1 \
  160.     x = *(int*)(base + (int)STATUS); \
  161.     pause(); \
  162.     y = (*(int*)(base + (int)(STATUS))) ^ 0x80; \
  163.     x = *(int*)(base + (int)NUL_CMD); \
  164.  
  165. #define READ_STAT_FAST \
  166.     x = *(int*)(base + (int)STATUS); \
  167.     pause(); \
  168.     y = (*(int*)(base + (int)(STATUS))) ^ 0x80; \
  169.  
  170. #define READ_STAT(cmd) \
  171.     x = *(int*)(base + (int)(cmd | WRITE_STROBE)); \
  172.     delay(); \
  173.     x = *(int*)(base + (int)(cmd)); \
  174.     delay(); \
  175.     y = (*(int*)(base + (int)(cmd)) & 0xf0) ^ 0x80; \
  176.     x = *(int*)(base + (int)(NUL_CMD + WRITE_STROBE)); \
  177.     delay(); \
  178.     x = *(int*)(base + (int)(last = NUL_CMD)); \
  179.     delay(); \
  180.          
  181. #define READ_SUB_FAST(cmd) \
  182.     x = *(int*)(base + (int)(cmd)); \
  183.     x = (*(int*)(base + (int)(cmd))) & 0xf0; \
  184.     x >>= 4; \
  185.        y = *(int*)(base + (int)(cmd + WRITE_STROBE)); \
  186.      y = (((*(int*)(base + (cmd | WRITE_STROBE)) & 0xf0)) | x); \
  187.     y ^= 0x88; \
  188.  
  189. #define READ_SUPER_FAST(cmd) \
  190. /*    x = *(int*)(base + (int)(cmd));*/ \
  191.     x = (*(int*)(base + (int)(cmd))) & 0xf0; \
  192.     x >>= 4; \
  193. /*       y = *(int*)(base + (int)(cmd + WRITE_STROBE));*/ \
  194.      y = (((*(int*)(base + (cmd | WRITE_STROBE)) & 0xf0)) | x); \
  195.     y ^= 0x88; \
  196.  
  197. #define READ_HYPER_FAST(cmd) \
  198.     x = (*(int*)(base + (int)(cmd))) & 0xf0; \
  199.     x >>= 4; \
  200.      y = (((*(int*)(base + (cmd | WRITE_STROBE)) & 0xf0)) | x); \
  201.     y ^= 0x88; \
  202.  
  203. int copyEAD()
  204. {
  205.   register byte *base = (byte*)NIC_BASE;
  206.   register int x,y;
  207.   int i;
  208.  
  209.   WRITE_SUB_FAST(0,RW_ADR);
  210.   WRITE_SUB_FAST(HA13,RW_ADR);
  211.  
  212.   for(i = 0; i < EADDR_LEN;i++) 
  213.   {
  214.     READ_SUB_FAST(READ);
  215.     our_address[i] = y;
  216.   }
  217.   if(   our_address[0] == 0x00 
  218.      && our_address[1] == 0xde 
  219.      && our_address[2] == 0x15)
  220.   {
  221.     our_address[1] = 0x80;
  222.     our_address[2] = 0xc8;
  223.  
  224.     /* our_address[3] &= 0x0f;
  225.        our_address[3] |= 0x70; */
  226.   }
  227.   else
  228.   {
  229.     return -1;
  230.   }
  231.  
  232.   WRITE_SUB_FAST(0,RW_ADR);
  233.   WRITE_SUB_FAST(HA13,RW_ADR);
  234.  
  235.   for(i = 0;i < EADDR_LEN;i++) 
  236.   {
  237.     WRITE_SUB_FAST(our_address[i],WRITE);
  238.   }
  239.   x++;
  240.   return 0;
  241. }
  242.  
  243. int Check_DE600()
  244. {
  245.   register byte *base = (byte*)NIC_BASE;
  246.   register int x,y;
  247.  
  248.   x = *(int*)(base + NUL_CMD);
  249.   delay();
  250.   WRITE_SUB(RESET,COMMAND);
  251.   delay();
  252.   WRITE_SUB(STOP_RESET,COMMAND);
  253.   delay();
  254.   READ_STAT(STATUS);
  255.   x++;     
  256.   if(y == 0) return 0;
  257.   else return -1;
  258. }
  259.  
  260. int send_packet(byte *p_pkt, int pkt_len)
  261. {
  262.   register byte *base = (byte*)NIC_BASE;
  263.   register int x,y,TxStartAdd,val;
  264.   int loop_cnt;
  265.   void lnc_check(void);
  266.  
  267.   if(pkt_len < RUNT) pkt_len = RUNT;
  268.   pkt_len = (pkt_len+1) & ~1;  /* make sure min. size */
  269.  
  270.   CurTxPage ^= 0x8;        /* next free buffer */
  271.  
  272.   TxStartAdd = (BFRSIZ - pkt_len) | ((int)CurTxPage << 8);
  273.   WRITE_SUB_FAST(TxStartAdd & 0xff, RW_ADR);  
  274.   WRITE_SUB_FAST(TxStartAdd >> 8, RW_ADR);  
  275.  
  276.   while(pkt_len--)
  277.   {
  278.     val = *p_pkt++;
  279.     WRITE_SUPER_FAST(val,WRITE);
  280.   }
  281.   last = ( ( ( (int)(*(p_pkt-1)) << 1) & 0x1e0) + ((WRITE) ^ WRITE_STROBE));
  282.  
  283.   for(loop_cnt = 0x4000;loop_cnt--;)
  284.   {
  285.     y = (*(int*)(base + (int)last)) ^ 0x80;
  286.     if((y & TXBUSY) == 0) break;
  287.   }
  288.  
  289.   LastTxStartAdd = TxStartAdd;
  290.   WRITE_SUB_FAST(TxStartAdd & 0xff, TX_ADR);
  291.   WRITE_SUB_FAST(TxStartAdd >> 8, TX_ADR);
  292.   WRITE_SUB_FAST(Mode_RxPg | RXEN, COMMAND);
  293.   WRITE_SUB_FAST(Mode_RxPg | RXEN | TXEN, COMMAND);
  294.   mode = TXEN | RXEN;
  295.  
  296.   x++;
  297.   return pkt_len;
  298. }
  299.  
  300. int test_mem()
  301. {
  302.   register byte *base = (byte*)NIC_BASE;
  303.   register int x,y,i;
  304.  
  305.   locked200 |= LOCKMEM;
  306.   
  307.   WRITE_SUB_FAST(0,RW_ADR);
  308.   WRITE_SUB_FAST(0,RW_ADR);
  309.   for(i = 0;i < 0x800;i++)
  310.   {
  311.     WRITE_SUB_FAST(i & 0xff,WRITE);
  312.   }
  313.   WRITE_SUB_FAST(0,RW_ADR);
  314.   WRITE_SUB_FAST(0,RW_ADR);
  315.   for(i=0;i<0x800;i++)
  316.   {
  317.     READ_SUB_FAST(READ);
  318.     if((i & 0xff) != y)
  319.     {
  320.       Cconws("\r\nDE600 memory test error!!\r\n");
  321.       locked200 &= ~LOCKMEM;
  322.       return -1;
  323.     }
  324.   }
  325.   x++;
  326.   locked200 &= ~LOCKMEM;
  327.   return 0;
  328. }
  329.  
  330. int resetNIC(void)
  331. {
  332.   int copyEAD(void);
  333.   int Check_DE600(void);
  334.   int test_mem(void);
  335.   void enable_rcv(void);
  336.  
  337.   CurRxPage = 0x20;
  338.   Mode_RxPg = RX_BP | 0x20;
  339.   CurTxPage = 0;
  340.  
  341.   if(Check_DE600()) return -1;
  342.   if(test_mem()) return -1;
  343.   if(copyEAD()) return -1;
  344.   enable_rcv();
  345.   return 0; 
  346. }
  347.  
  348. void stopNIC(void)
  349. {
  350.   register byte *base = (byte*)NIC_BASE;
  351.   register int x;
  352.  
  353.   WRITE_SUB_FAST(Mode_RxPg, COMMAND);
  354.   x++; 
  355. }
  356.  
  357. byte NICstatus()
  358. {
  359.   register byte *base = (byte*)NIC_BASE;
  360.   register int x,y;
  361.  
  362.   READ_STAT1;
  363.   x++;
  364.   return y;
  365. }
  366.  
  367. void enable_rcv()
  368. {
  369.   register byte *base = (byte*)NIC_BASE;
  370.   register int x;
  371.  
  372.   WRITE_SUB_FAST(Mode_RxPg, COMMAND);
  373.   WRITE_SUB_FAST(Mode_RxPg | RXEN, COMMAND);
  374.   mode = RXEN;
  375.   x++;
  376. }
  377.  
  378. int read_inf(void)
  379. {
  380.   COOKIE *cookie;
  381.  
  382.   cookie = get_cookie(INETCUSTCOOKIE);
  383.   if(!cookie || !cookie->val) return(0);
  384.   return(1);
  385. }
  386.  
  387. int net_info(int len, char *buf)
  388. {
  389.  
  390.   locked200 |= LOCKNET;
  391.  
  392.   if(!buf)
  393.   {
  394.     Mode_RxPg = (Mode_RxPg & 0xfc) | len;
  395.     locked200 &= ~LOCKNET;
  396.     return(0);
  397.   }
  398.   if(buf == (char *)1L) 
  399.   {
  400.     resetNIC();
  401.     locked200 &= ~LOCKNET;
  402.     return(0);
  403.   }
  404.   stat.st_free = freecnt;
  405.   memcpy(buf,(char *)&stat,(size_t)len<sizeof(stat)?len:(int)sizeof(stat));
  406.  
  407.   locked200 &= ~LOCKNET;
  408.   return(len);
  409. }
  410.  
  411. int net_open(int type, int (*handler)(int,char *))
  412. {
  413.   int i,new;
  414.  
  415.   if(!handler) return(EPARAM);
  416.   if(protocols >= MAXPROTOCOLS) return(EPROTAVAIL);
  417.   new = -1;
  418.   locked200 |= LOCKNET;
  419.   if(!protocols)
  420.   {
  421.     if(net_reset() < 0)
  422.     {
  423.       locked200 &= ~LOCKNET;
  424.       return(EINIT);
  425.     }
  426.   }
  427.   for(i = 0; i < MAXPROTOCOLS; i++)
  428.   {
  429.     /* protocol already used */
  430.     if(protos[i].type == type)
  431.     {
  432.       locked200 &= ~LOCKNET;
  433.       return(EPROTUSED);
  434.     }
  435.     if(protos[i].type == ET_UNUSED &&  new<0 ) new = i;  /* find first free entry */
  436.   }
  437.   if(new < 0) new = protocols;
  438.   protocols++;
  439.   protos[new].handler = handler;
  440.   protos[new].recvd = 0;
  441.   protos[new].sent = 0;
  442.   protos[new].type = type;
  443.   locked200 &= ~LOCKNET;
  444.   return(new);
  445. }
  446.  
  447. int net_release(int type)
  448. {
  449.   int i;
  450.   void stopNIC(void);
  451.  
  452.   if(!protocols) return(EPROTUSED);
  453.   if(type == ET_UNUSED) return(EPROTUSED);
  454.  
  455.   for(i=0; i < MAXPROTOCOLS; i++)
  456.     if(protos[i].type == type) break;
  457.   if(i==MAXPROTOCOLS)
  458.   {
  459.     return(EPROTUSED);
  460.   }
  461.   locked200 |= LOCKNET;
  462.   protocols--;
  463.   if(!protocols)
  464.   {
  465.     stopNIC();
  466.   }
  467.   protos[i].type = ET_UNUSED;
  468.   protos[i].handler = NULL;
  469.   locked200 &= ~LOCKNET;
  470.   return(protocols);
  471. }
  472.  
  473. int net_send(int len, char *buf)
  474. {
  475.   register byte *base = (byte*)NIC_BASE;
  476.   register long timeout;
  477.   register int y;
  478.  
  479.   void lnc_check(void);
  480.   byte NICstatus(void);
  481.   void enable_rcv(void);
  482. #ifdef DEBI
  483.   printf("netsend %lx length %d good = %d mode = %x\n",buf,len,good,mode);
  484. #endif
  485.  
  486.   if(!buf || !len || (buf < (char *)PPKT) || (buf > (char *)&PPOOL)) return(EPARAM);
  487.   if(len < 60) len = 60;
  488.   if(len > (int)sizeof(PACKET)) return(EPKTLEN);
  489.  
  490.   locked200 |= LOCKNET;
  491.   timeout = clock() + 3*TIMEOUT;
  492.   len = send_packet((byte*)buf,len);
  493.  
  494. #ifdef DEBI    
  495.   printf("send done\n");
  496. #endif
  497.   locked200 &= ~LOCKNET;
  498.   return(0);
  499. }
  500.  
  501. int    net_getadr(int len, char *buf)
  502. {
  503.   if(len >= (int)sizeof(HADDR))
  504.   {
  505.     buf[0] = our_address[0];
  506.     buf[1] = our_address[1];
  507.     buf[2] = our_address[2];
  508.     buf[3] = our_address[3];
  509.     buf[4] = our_address[4];
  510.     buf[5] = our_address[5];
  511.     return((int)sizeof(HADDR));
  512.   }
  513.   return(0);
  514. }
  515.  
  516. int net_reset(void)
  517. {
  518.   int i,tmp;
  519.  
  520.   locked200 |= LOCKRES;
  521.   for(i=0;i<MAXPROTOCOLS;i++)  /* init protocol table */
  522.   {
  523.     protos[i].type = ET_UNUSED;
  524.     protos[i].handler = NULL;
  525.     protos[i].recvd = 0;
  526.     protos[i].sent = 0;
  527.   }
  528.   protocols = 0;
  529.  
  530.   p_free = p_init(MAXPKT,&PPOOL,PPKT);  /* init free packets */
  531.   freecnt = MAXPKT;
  532.  
  533.   tmp = resetNIC();
  534.   locked200 &= ~LOCKRES;
  535.   return tmp;
  536. }
  537.  
  538. PKTBUF *net_pktalloc(protocol)
  539. u_short protocol;
  540. {
  541.   PKTBUF * tmp;
  542.  
  543.   if(!p_free) net_reset();
  544.   
  545.   locked200 |= LOCKALLO;
  546.   if(freecnt <= 1)
  547.   {
  548. Bconws("DLINKDRV: No free Packet\r");
  549.     locked200 &= ~LOCKALLO;
  550.     return(NULL);
  551.   }
  552.   freecnt--;
  553.   tmp = ap_getpkt(protocol,p_free);
  554. #ifdef DEBUGPKT
  555.   sprintf(str,"netpktalloc at %lx\r",tmp);
  556.   Bconws(str);
  557. #endif
  558.   locked200 &= ~LOCKALLO;
  559.   return tmp;
  560. }
  561.  
  562. int net_pktfree(p_pkt)
  563. PKTBUF *p_pkt;
  564. {
  565.   locked200 |= LOCKFREE;
  566. #ifdef DEBUGPKT
  567.   sprintf(str,"netpktfree at %lx\r",p_pkt);
  568.   Bconws(str);
  569. #endif
  570.   if(!p_free || !p_pkt || (p_pkt < PPKT) || (p_pkt > &PPKT[MAXPKT-1]))
  571.   {
  572.     Bconws("DLINKDRV: Packet out of bounds\r");
  573.     locked200 &= ~LOCKFREE;
  574.     return(FALSE);
  575.   }
  576.   if(((long)p_pkt - (long)PPKT) % sizeof(PKTBUF))
  577.   {
  578.     Bconws("DLINKDRV: Packet misaligned\r");
  579.     locked200 &= ~LOCKFREE;
  580.     return(FALSE);
  581.   }
  582.   if(ap_putpkt(p_free,p_pkt))
  583.   {
  584.     freecnt++;
  585.     locked200 &= ~LOCKFREE;
  586.     return(TRUE);
  587.   }
  588.   Bconws("DLINKDRV: Packet not freed\r");
  589.   locked200 &= ~LOCKFREE;
  590.   return(FALSE);
  591. }
  592.  
  593. /*******************************************************************/
  594. /* read D-LINK function                                            */
  595. /*******************************************************************/
  596.  
  597. void lnc_check(void)
  598. {
  599.   register byte *base = (byte*)NIC_BASE;
  600.   register int x,y,i,ii,NICstate;
  601.   int        type, RxPktLen, loop;
  602.  
  603.   et_stat    *et_stat;
  604.   PKTBUF        *pkt;
  605.   byte * pb;
  606.  
  607.   locked200 |= LOCKREC;
  608.  
  609.   for(loop = 0;loop < 1;loop++)
  610.   {
  611.     x = *(int*)(base + (int)STATUS);
  612.     y = *(int*)(base + (int)STATUS);
  613.     x = *(int*)(base + (int)NUL_CMD);
  614.     NICstate = y; 
  615.  
  616.     if(NICstate & GOOD)
  617.     {
  618.       READ_SUPER_FAST(RX_LEN);
  619.       RxPktLen = y;
  620.       READ_SUPER_FAST(RX_LEN);
  621.       RxPktLen += (y << 8);
  622.  
  623.       Mode_RxPg ^= 0x10;
  624.       WRITE_SUB_FAST(Mode_RxPg, COMMAND);
  625.       WRITE_SUB_FAST(Mode_RxPg | RXEN, COMMAND);
  626.       mode = RXEN;
  627.       WRITE_SUB_FAST(0,RW_ADR);
  628.       WRITE_SUB_FAST(CurRxPage >> 1,RW_ADR);
  629.       CurRxPage ^= 0x10;
  630.       RxPktLen -= 4;
  631.       et_stat = &stat;
  632.       et_stat->st_err = NICstate;
  633.       et_stat->st_intr++;
  634.  
  635.       pb = (byte*)&header;
  636.       for(i=0; i < 14;i++)
  637.       {
  638.         READ_SUPER_FAST(READ);
  639.         *pb++ = y;
  640.       }
  641.       type = header.et_type;
  642.       et_stat->st_received++;
  643.  
  644.       if(header.et_dest[0] != 0xff)
  645.       {
  646.           for(i = 0;i < MAXPROTOCOLS; i++)
  647.           {
  648.             if(protos[i].type == type)
  649.             {
  650.               /* must have one packet free */
  651.               if((pkt = ap_getpkt(type,p_free)) != 0)
  652.               {
  653.                 freecnt--;
  654.                 memcpy((char*)pkt,(char*)&header,sizeof(et_hdr));
  655.                 pb = pkt->et_data;
  656.                 for(ii=(int)sizeof(et_hdr); ii < RxPktLen; ii++)
  657.                 {
  658.                   READ_SUPER_FAST(READ);
  659.                   *pb++ = y;
  660.                 }
  661.                 if(protos[i].handler)
  662.                 { 
  663.                  if(protos[i].handler(RxPktLen,(char *)pkt))
  664.                  {
  665.                   et_stat->st_got++;
  666.                   protos[i].recvd++;
  667.                  }
  668.                 }
  669.                 else
  670.                 {
  671.                 /* free unused packet */
  672.                   if(ap_putpkt(p_free,pkt)) freecnt++;
  673.                   break;
  674.                 }
  675.               }
  676.             }
  677.           }
  678.       }
  679.     }
  680.     else
  681.     {
  682.       WRITE_SUB_FAST(Mode_RxPg, COMMAND);
  683.       WRITE_SUB_FAST(Mode_RxPg | RXEN, COMMAND);
  684.       if(loop == 0) break;
  685.     }
  686.     
  687.     if(NICstate & T16)
  688.     {
  689.       et_stat->st_xmiterr++;
  690.     }
  691.   }
  692.   x++;
  693.   locked200 &= ~LOCKREC;
  694. }
  695.  
  696. int main()
  697. {
  698.   COOKIE *cookie;
  699.   int (*call)(void);
  700.   long lance_install(void);
  701.  
  702.   Cconws("\r\nPacket driver V1.1 for Dlink DE600 ");
  703.   cookie = get_cookie(PKTCOOKIE);
  704.   if(cookie)
  705.   {
  706.     (long)call = ((long *)cookie->val)[NETRESET];
  707.     if(call() == 0)  /* reset network */
  708.       Cconws("\r\nexisting driver reset\r\n");
  709.     else 
  710.       Cconws("\r\ncould not reset existing driver\r\n");
  711.     return 0;
  712.   }
  713.   if(!read_inf())
  714.   {
  715.     Cconws("INETCUST not installed !!\r\n");
  716.     return 1;
  717.   }
  718.   else
  719.   {
  720.     if(net_reset() < 0)
  721.     {
  722.       Cconws("\r\nno DE600 detected !!\r\n");
  723.       return 1;
  724.     }
  725.     locked200 |= LOCKMAIN;
  726.     if((int)Supexec(lance_install) < 0)
  727.     {
  728.       Cconws("\r\ncould not install handler !!\n");
  729.       return 1;
  730.     }
  731.     add_cookie(PKTCOOKIE,(long)ext_tab);
  732.     Cconws("installed\r\n(c) pm FORTec 1992\r\n");
  733.     locked200 &= ~LOCKMAIN;
  734.     Ptermres(_PgmSize,0);
  735.   }
  736.   return 0;
  737. }
  738.  
  739. long lance_install()
  740. {
  741.   void lnc_check(void);
  742. /*  long **vblqueue = *(long***)0x456L;
  743.   int vblnum = *(int*)0x454L;
  744.   int i;
  745.  
  746.   for(i=1; i< vblnum;i++) if (*(vblqueue+i) == 0L) break;
  747.  
  748.   if(i< vblnum) 
  749.   {
  750.     *(vblqueue+i) = (long*)lance_interrupt;
  751.     ihandler = (void (interrupt *)())lnc_check;
  752.     return 0;
  753.   }
  754.   else return -1;
  755. */
  756. old200 = (long*)Setexc(69,lance_200interrupt);
  757. ihandler = (void (interrupt *)())lnc_check;
  758. /*  old200 = *(long*)0x400;
  759.   *(long*)0x400 = (long)lance_200interrupt;*/
  760.   return 0;
  761. }
  762.